﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Linq;
using MoneyBook.Reflection;

namespace MoneyBook.ComponentModel.DataAnnotations {
    public static class CustomValidator {

        public static void TryValidateProperty(object value, ValidationContext context, ICollection<ValidationResult> validationResults) {
            Type targetType = context.ObjectType;
            if (context.ObjectInstance is ICustomTypeProvider) {
                targetType = ((ICustomTypeProvider)context.ObjectInstance).GetCustomType();
            }
            
            PropertyInfo propInfo = targetType.GetProperty(context.MemberName);
            if (propInfo == null) {
                //TODO: Error Message
                throw new ArgumentException(string.Format("{0} property not found.", context.MemberName), "propertyName");
            }
            
            string displayName = GetDisplayName(propInfo);
            ValidationAttribute[] attrs = propInfo.GetCustomAttributes(true)
                                        .Where(o => o is ValidationAttribute)
                                        .Select(o => o as ValidationAttribute).ToArray();

            RequiredAttribute requiredAttr = attrs.FirstOrDefault(a => a is RequiredAttribute) as RequiredAttribute;
            if (requiredAttr != null) {
                ValidationResult result = requiredAttr.GetValidationResult(value, context);
                if (result != ValidationResult.Success) {
                    result.ErrorMessage = requiredAttr.FormatErrorMessage(displayName);
                    validationResults.Add(result);
                    return;
                }
            }

            foreach (ValidationAttribute attr in attrs) {
                ValidationResult result = attr.GetValidationResult(value, context);
                if (result != ValidationResult.Success) {
                    result.ErrorMessage = attr.FormatErrorMessage(displayName);                    
                    validationResults.Add(result);
                }
            }
        }

        private static string GetDisplayName(PropertyInfo propInfo) {
            DisplayAttribute attr = propInfo.GetSingleCustomAttribute<DisplayAttribute>(true);
            if (attr != null) {
                return attr.GetName();
            }
            return propInfo.Name;
        }
    }
}
